package com.millstein.tsinglog.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.millstein.tsinglog.commons.constant.SystemConstant;
import com.millstein.tsinglog.commons.enums.ResultCode;
import com.millstein.tsinglog.exception.TsinglogException;
import com.millstein.tsinglog.commons.service.BaseService;
import com.millstein.tsinglog.mapper.biz.CategoryMapper;
import com.millstein.tsinglog.model.dto.category.CategorySaveDTO;
import com.millstein.tsinglog.model.pojo.Category;
import com.millstein.tsinglog.model.vo.biz.CategoryVo;
import com.millstein.tsinglog.model.vo.result.PageResult;
import com.millstein.tsinglog.service.CategoryService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import tk.mybatis.mapper.entity.Example;

import java.util.ArrayList;
import java.util.List;

@Service
public class CategoryServiceImpl extends BaseService implements CategoryService {

    @Autowired
    private CategoryMapper categoryMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public List<Category> getAllCategory() {
        Category category = new Category();
        // 查询状态正常的分类
        category.setStatus(SystemConstant.STATUS_ENTITY_NORMAL);
        List<Category> list = categoryMapper.select(category);
        if (CollectionUtils.isEmpty(list)) {
            throw new TsinglogException(ResultCode.RETURN_DATA_NOT_FOUND);
        }
        return list;
    }

    @Override
    public PageResult<Category> getCategoryByPage(Integer currentPage, Integer pageSize, String keyword) {
        // 1.对参数进行校验
        if (currentPage == null) {
            currentPage = SystemConstant.DEFAULT_CURRENT_PAGE;
        }
        if (pageSize == null) {
            pageSize = SystemConstant.DEFAULT_PAGE_SIZE;
        }

        Example example = new Example(Category.class);
        Example.Criteria criteria = example.createCriteria();

        // 2.条件搜索
        if (StringUtils.isNotBlank(keyword)) {
            criteria.andLike("categoryName", "%" + keyword + "%");
        }
        // 3.过滤只查询状态为正常的分类信息
        criteria.andEqualTo("status", SystemConstant.STATUS_ENTITY_NORMAL);
        // 4.按照排序列的升序进行排序
        example.setOrderByClause("usable desc, sort asc");
        // 5.分页查询
        PageHelper.startPage(currentPage, pageSize);
        List<Category> list = categoryMapper.selectByExample(example);
        PageInfo pageInfo = new PageInfo(list);
        return new PageResult<Category>(pageInfo.getTotal(), pageInfo.getPages(), list);
    }

    private Category getCategoryByCategoryName(String categoryName) {
        Category category = new Category();
        category.setCategoryName(categoryName);
        category.setStatus(SystemConstant.STATUS_ENTITY_NORMAL);
        return categoryMapper.select(category).size() == 0 ? null: categoryMapper.select(category).get(0);
    }

    @Override
    public void insertCategory(CategorySaveDTO categorySaveDTO) {

        if (this.getCategoryByCategoryName(categorySaveDTO.getName()) != null) {
            throw new TsinglogException(ResultCode.EXISTS_SAME_CATEGORY);
        }

        Category category = new Category();
        category.setCategoryName(categorySaveDTO.getName());
        category.setDescription(categorySaveDTO.getDesc());
        // 如果不指定sort的值，那么默认设置为1，即最高优先级
        if (StringUtils.isNotBlank(categorySaveDTO.getSort())) {
            category.setSort(Integer.parseInt(categorySaveDTO.getSort()));
        } else {
            category.setSort(SystemConstant.FIRST_PRIORITY);
        }
        category.setUsable(SystemConstant.USABLE_ENTITY_ON);
        category.setStatus(SystemConstant.STATUS_ENTITY_NORMAL);
        category.setCreateTime(getCurrentDateStr());
        category.setUpdateTime(getCurrentDateStr());

        int result = categoryMapper.insertSelective(category);
        if (result != 1) {
            throw new TsinglogException(ResultCode.INSERT_FAILURE);
        }

        redisTemplate.delete(SystemConstant.REDIS_KEY_FOR_CATEGORY_LIST);
    }

    @Override
    @Transactional
    public void deleteByIds(List<Long> ids) {
        if (CollectionUtils.isEmpty(ids)) {
            throw new TsinglogException(ResultCode.PARAM_IS_BLANK);
        }

        for (Long id: ids) {
            Category category = categoryMapper.selectCategoryByPrimaryKeyForServer(id);
            if (category == null) {
                throw new TsinglogException(ResultCode.RETURN_DATA_NOT_FOUND);
            }

            category.setStatus(SystemConstant.STATUS_ENTITY_DELETE);
            category.setUpdateTime(getCurrentDateStr());

            int result = categoryMapper.updateByPrimaryKeySelective(category);
            if (result != 1) {
                throw new TsinglogException(ResultCode.DELETE_FAILURE);
            }
        }
        redisTemplate.delete(SystemConstant.REDIS_KEY_FOR_CATEGORY_LIST);
    }

    @Override
    public void changeUsable(Long id, Short usable) {
        if (id == null || usable == null) {
            throw new TsinglogException(ResultCode.PARAM_IS_BLANK);
        }

        Category category = categoryMapper.selectCategoryByPrimaryKeyForServer(id);
        if (category == null) {
            throw new TsinglogException(ResultCode.RETURN_DATA_NOT_FOUND);
        }

        category.setUsable(usable);
        category.setUpdateTime(getCurrentDateStr());
        int result = categoryMapper.updateByPrimaryKeySelective(category);

        if (result != 1) {
            throw new TsinglogException(ResultCode.UPDATE_FAILURE);
        }

        redisTemplate.delete(SystemConstant.REDIS_KEY_FOR_CATEGORY_LIST);
    }

    @Override
    public Category getCategoryById(Long id) {
        if (id == null) {
            throw new TsinglogException(ResultCode.PARAM_IS_BLANK);
        }

        Category category = categoryMapper.selectCategoryByPrimaryKeyForServer(id);
        if (category == null) {
            throw new TsinglogException(ResultCode.RETURN_DATA_NOT_FOUND);
        }
        return category;
    }

    @Override
    public void updateCategory(CategorySaveDTO categorySaveDTO) {

        Long id = categorySaveDTO.getId();
        if (id == null) {
            throw new TsinglogException(ResultCode.RETURN_DATA_NOT_FOUND);
        }

        if (this.getCategoryByCategoryName(categorySaveDTO.getName()) != null) {
            throw new TsinglogException(ResultCode.EXISTS_SAME_CATEGORY);
        }

        Category dbCategory = categoryMapper.selectCategoryByPrimaryKeyForServer(id);
        if (dbCategory == null) {
            throw new TsinglogException(ResultCode.RETURN_DATA_NOT_FOUND);
        }

        dbCategory.setCategoryName(categorySaveDTO.getName());
        dbCategory.setDescription(categorySaveDTO.getDesc());
        dbCategory.setSort(Integer.parseInt(categorySaveDTO.getSort()));
        dbCategory.setUpdateTime(getCurrentDateStr());

        int result = categoryMapper.updateByPrimaryKeySelective(dbCategory);
        if (result != 1) {
            throw new TsinglogException(ResultCode.UPDATE_FAILURE);
        }

        redisTemplate.delete(SystemConstant.REDIS_KEY_FOR_CATEGORY_LIST);
    }

    @Override
    public List<CategoryVo> getAllCategoryForPortal() {

        ValueOperations operations = redisTemplate.opsForValue();

        if (redisTemplate.hasKey(SystemConstant.REDIS_KEY_FOR_CATEGORY_LIST)) {
            return (List<CategoryVo>) operations.get(SystemConstant.REDIS_KEY_FOR_CATEGORY_LIST);
        }

        Category criteria = new Category();
        // 查询状态正常的分类
        criteria.setStatus(SystemConstant.STATUS_ENTITY_NORMAL);
        criteria.setUsable(SystemConstant.USABLE_ENTITY_ON);
        List<Category> list = categoryMapper.select(criteria);

        List<CategoryVo> voList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(list)) {
            for (Category category : list) {
                CategoryVo vo = new CategoryVo(category);
                vo.setLink(SystemConstant.PORTAL_SEARCH_URL + "?cid=" + category.getId());
                voList.add(vo);
            }
        }

        operations.set(SystemConstant.REDIS_KEY_FOR_CATEGORY_LIST, voList);

        return voList;
    }
}
